home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / swtools / libdwarf / dwarf_line.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  43.3 KB  |  1,424 lines

  1. /*
  2.     dwarf_line.c
  3.     $Revision: 1.34 $  $Date: 1994/06/17 02:39:41 $
  4.  
  5.     The comsumer line table functions.
  6.  
  7.  
  8. */
  9.  
  10. #include <stdio.h>
  11. #include "dwarf_incl.h"
  12. #include "dwarf_line.h"
  13.  
  14.  
  15. /* 
  16.     Although source files is supposed to return the
  17.     source files in the compilation-unit, it does
  18.     not look for any in the statement program.  In
  19.     other words, it ignores those defined using the
  20.     extended opcode DW_LNE_define_file.
  21. */
  22. int
  23. dwarf_srcfiles (
  24.     Dwarf_Die       die,
  25.     char              ***srcfiles,
  26.     Dwarf_Signed    *srcfilecount,
  27.     Dwarf_Error     *error
  28. )
  29. {
  30.         /* 
  31.             This pointer is used to scan the portion of  
  32.             the .debug_line section for the current cu.  
  33.         */
  34.     Dwarf_Small     *line_ptr;      
  35.  
  36.         /* 
  37.             This points to the last byte of the         
  38.             .debug_line portion for the current cu. 
  39.         */
  40.     Dwarf_Small     *line_ptr_end;  
  41.  
  42.         /* 
  43.             This points to the end of the statement program prologue
  44.             for the current cu, and serves to check that the prologue   
  45.             was correctly decoded.                                      
  46.         */
  47.     Dwarf_Small     *check_line_ptr;
  48.  
  49.     /* 
  50.         Pointer to a DW_AT_stmt_list attribute 
  51.         in case it exists in the die.
  52.     */
  53.     Dwarf_Attribute    stmt_list_attr;
  54.  
  55.     /* Pointer to DW_AT_comp_dir attribute in die. */
  56.     Dwarf_Attribute    comp_dir_attr;
  57.  
  58.     /* Pointer to name of compilation directory. */
  59.     Dwarf_Small        *comp_dir = 0;
  60.  
  61.     /* 
  62.         Offset into .debug_line specified by a 
  63.         DW_AT_stmt_list attribute.
  64.     */
  65.     Dwarf_Unsigned    line_offset;
  66.  
  67.         /* Some of the fields of the statement program header. */
  68.     Dwarf_Unsigned          total_length;
  69.     Dwarf_Half              version;
  70.     Dwarf_Unsigned          prologue_length;
  71.     Dwarf_Small            opcode_base;
  72.  
  73.     /* File name excluding included directory. */
  74.     char            *file_name;
  75.  
  76.     /* Name of directory that the file is in. */
  77.     char            *dir_name;
  78.  
  79.     /* Name concatenating both directory and file name. */
  80.     char            *full_name;
  81.  
  82.     /* 
  83.         This is the directory index for the file.
  84.         The compilation directory is 0, and the
  85.         first included directory is 1.
  86.     */
  87.     Dwarf_Sword                dir_index;
  88.  
  89.     Dwarf_Small             *include_directories;
  90.     
  91.     Dwarf_Sword                i, file_count, directories_count;
  92.  
  93.         /* 
  94.             This is the current opcode read     
  95.             from the statement program.     
  96.         */
  97.     Dwarf_Small         opcode;
  98.  
  99.     Dwarf_Word          leb128_length;
  100.  
  101.         /* This is the length of an extended opcode instr.  */
  102.     Dwarf_Sword         instr_length;
  103.     Dwarf_Small         ext_opcode;
  104.  
  105.         /* 
  106.             This points to a block of char *'s, 
  107.         each of which points to a file name.
  108.         */
  109.     char          **ret_files;
  110.  
  111.     /* The Dwarf_Debug this die belongs to. */
  112.     Dwarf_Debug        dbg;
  113.  
  114.     /* Used to chain the file names. */
  115.     Dwarf_Chain        curr_chain, prev_chain, head_chain = NULL;
  116.     int resattr;
  117.      int lres;
  118.  
  119.     /* ***** BEGIN CODE ***** */
  120.  
  121.         /* Reset error. */
  122.     if (error != NULL) *error = NULL;
  123.  
  124.     CHECK_DIE(die, DW_DLV_ERROR)
  125.     dbg = die->di_cu_context->cc_dbg;
  126.  
  127.     resattr = dwarf_attr(die, DW_AT_stmt_list,&stmt_list_attr,error);
  128.     if(resattr != DW_DLV_OK) {
  129.     return resattr;
  130.     }
  131.  
  132.     if (dbg->de_debug_line == NULL) {
  133.         _dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_NULL);
  134.         return(DW_DLV_ERROR);
  135.     }
  136.  
  137.     lres  = dwarf_formudata(stmt_list_attr,&line_offset, error);
  138.     if(lres != DW_DLV_OK) {
  139.     return lres;
  140.     }
  141.     if (line_offset >= dbg->de_debug_line_size) {
  142.         _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
  143.         return(DW_DLV_ERROR);
  144.     }
  145.     line_ptr = dbg->de_debug_line + line_offset;
  146.     dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR);
  147.  
  148.     /* 
  149.         If die has DW_AT_comp_dir attribute, get the
  150.         string that names the compilation directory.
  151.     */
  152.     resattr = dwarf_attr(die, DW_AT_comp_dir,&comp_dir_attr, error);
  153.     if(resattr == DW_DLV_ERROR) {
  154.     return resattr;
  155.     }
  156.     if (resattr == DW_DLV_OK) {
  157.     int cres;
  158.     char *cdir;
  159.     cres = dwarf_formstring(comp_dir_attr,&cdir, error);
  160.     if(cres == DW_DLV_ERROR){
  161.         return cres;
  162.     }else if(cres == DW_DLV_OK) {
  163.         comp_dir = cdir;
  164.     }
  165.     }
  166.     if(resattr == DW_DLV_OK) {
  167.        dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
  168.     }
  169.  
  170.         /* 
  171.             Following is a straightforward decoding of the  
  172.             statement program prologue information.         
  173.         */
  174.     READ_UNALIGNED(total_length, line_ptr, dbg->de_length_size);
  175.     line_ptr += dbg->de_length_size;
  176.     line_ptr_end = line_ptr + total_length;
  177.     if (line_ptr_end > dbg->de_debug_line + 
  178.         dbg->de_debug_line_size) {
  179.         _dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD); 
  180.         return(DW_DLV_ERROR);
  181.     }
  182.  
  183.     READ_UNALIGNED(version, line_ptr, sizeof(Dwarf_Half));
  184.     line_ptr += sizeof(Dwarf_Half);
  185.     if (version != CURRENT_VERSION_STAMP) {
  186.         _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
  187.         return(DW_DLV_ERROR);
  188.     }
  189.  
  190.     READ_UNALIGNED(prologue_length, line_ptr, dbg->de_length_size);
  191.     line_ptr += dbg->de_length_size;
  192.     check_line_ptr = line_ptr;
  193.  
  194.     /* Skip over minimum instruction length. */
  195.     line_ptr = line_ptr + sizeof(Dwarf_Small);
  196.  
  197.     /* Skip over default_is_stmt. */
  198.     line_ptr = line_ptr + sizeof(Dwarf_Small);
  199.  
  200.     /* Skip over line_base. */
  201.     line_ptr = line_ptr + sizeof(Dwarf_Sbyte);
  202.  
  203.     /* Skip over line_ptr. */
  204.     line_ptr = line_ptr + sizeof(Dwarf_Small);
  205.  
  206.     opcode_base = *(Dwarf_Small *)line_ptr;
  207.     line_ptr = line_ptr + sizeof(Dwarf_Small);
  208.  
  209.     for (i = 1; i < opcode_base; i++) {
  210.         /* Skip over opcode lengths for standard opcodes. */
  211.         line_ptr = line_ptr + sizeof(Dwarf_Small);
  212.     }
  213.  
  214.     directories_count = 0;
  215.     include_directories = line_ptr;
  216.     while ((*(char *)line_ptr) != '\0') {
  217.         line_ptr = line_ptr + strlen((char *)line_ptr) + 1;
  218.         directories_count++;
  219.     }
  220.     line_ptr++;
  221.  
  222.     file_count = 0;
  223.     while (*(char *)line_ptr != '\0') {
  224.  
  225.         file_name = (Dwarf_Small *)line_ptr;
  226.         line_ptr = line_ptr + strlen((char *)line_ptr) + 1;
  227.  
  228.     DECODE_LEB128_UWORD(line_ptr, dir_index)
  229.     if (dir_index > directories_count) {
  230.         _dwarf_error(dbg, error, DW_DLE_DIR_INDEX_BAD);
  231.         return(DW_DLV_ERROR);
  232.     }
  233.  
  234.     if (dir_index == 0)
  235.         dir_name = comp_dir;
  236.     else {
  237.         dir_name = include_directories;
  238.         for (i = 1; i < dir_index; i++)
  239.         dir_name = dir_name + strlen(dir_name) + 1;
  240.     }
  241.  
  242.     if ((*file_name) == '/') 
  243.         full_name = file_name;
  244.     else {
  245.         full_name = (char *)_dwarf_get_alloc(dbg, DW_DLA_STRING,
  246.         strlen(dir_name) + 1 + strlen(file_name) + 1);
  247.         if (full_name == NULL) {
  248.         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
  249.         return(DW_DLV_ERROR);
  250.         }
  251.  
  252.         strcpy(full_name, dir_name);
  253.         strcat(full_name, "/");
  254.         strcat(full_name, file_name);
  255.     }
  256.  
  257.         /* Skip over time of last modification. */
  258.         _dwarf_decode_u_leb128(line_ptr,&leb128_length);
  259.         line_ptr = line_ptr + leb128_length;
  260.  
  261.         /* Skip over file length. */
  262.         _dwarf_decode_u_leb128(line_ptr,&leb128_length);
  263.         line_ptr = line_ptr + leb128_length;
  264.  
  265.         curr_chain = 
  266.         (Dwarf_Chain)_dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
  267.     if (curr_chain == NULL) {
  268.         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); 
  269.         return(DW_DLV_ERROR);
  270.     }
  271.  
  272.     curr_chain->ch_item = full_name;
  273.  
  274.     if (head_chain == NULL)
  275.         head_chain = prev_chain = curr_chain;
  276.     else {
  277.         prev_chain->ch_next = curr_chain;
  278.         prev_chain = curr_chain;
  279.     }
  280.  
  281.         file_count++;
  282.     }
  283.     line_ptr++;
  284.  
  285.     if (line_ptr != check_line_ptr + prologue_length) {
  286.         _dwarf_error(dbg,error,DW_DLE_LINE_PROLOG_LENGTH_BAD);
  287.         return(DW_DLV_ERROR);
  288.     }
  289.  
  290.     if (file_count == 0) {
  291.     *srcfiles = NULL;
  292.     *srcfilecount = 0;
  293.     return(DW_DLV_NO_ENTRY);
  294.     }
  295.  
  296.     ret_files = (char **)
  297.         _dwarf_get_alloc(dbg, DW_DLA_LIST, file_count);
  298.     if (ret_files == NULL) {
  299.         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
  300.         return(DW_DLV_ERROR);
  301.     }
  302.  
  303.     curr_chain = head_chain;
  304.     for (i = 0; i < file_count; i++) {
  305.         *(ret_files + i) = curr_chain->ch_item;
  306.         prev_chain = curr_chain;
  307.         curr_chain = curr_chain->ch_next;
  308.         dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
  309.     }
  310.  
  311.     *srcfiles = ret_files;
  312.     *srcfilecount = file_count;
  313.     return(DW_DLV_OK);
  314. }
  315.  
  316.  
  317. /*
  318.     return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR
  319. */
  320. int
  321. _dwarf_internal_srclines (
  322.     Dwarf_Die       die,
  323.     Dwarf_Line      **linebuf,
  324.     Dwarf_Signed    *count,
  325.     Dwarf_Bool      doaddrs,
  326.     Dwarf_Bool      dolines,
  327.     Dwarf_Error     *error
  328. )
  329. {
  330.         /* 
  331.             This pointer is used to scan the portion of  
  332.             the .debug_line section for the current cu.  
  333.         */
  334.     Dwarf_Small     *line_ptr;      
  335.  
  336.         /* 
  337.             This points to the last byte of the         
  338.             .debug_line portion for the current cu. 
  339.         */
  340.     Dwarf_Small     *line_ptr_end;  
  341.  
  342.         /* 
  343.             This points to the end of the statement program prologue
  344.             for the current cu, and serves to check that the prologue   
  345.             was correctly decoded.                                      
  346.         */
  347.     Dwarf_Small     *check_line_ptr;
  348.  
  349.     /* 
  350.         Pointer to a DW_AT_stmt_list attribute 
  351.         in case it exists in the die.
  352.     */
  353.     Dwarf_Attribute    stmt_list_attr;
  354.  
  355.     /* Pointer to DW_AT_comp_dir attribute in die. */
  356.     Dwarf_Attribute    comp_dir_attr;
  357.  
  358.     /* Pointer to name of compilation directory. */
  359.     Dwarf_Small        *comp_dir = NULL;
  360.  
  361.     /* 
  362.         Offset into .debug_line specified by a 
  363.         DW_AT_stmt_list attribute.
  364.     */
  365.     Dwarf_Unsigned    line_offset;
  366.  
  367.         /* These are the fields of the statement program header. */
  368.     Dwarf_Unsigned          total_length;
  369.     Dwarf_Half              version;
  370.     Dwarf_Unsigned          prologue_length;
  371.     Dwarf_Small             minimum_instruction_length;
  372.     Dwarf_Small             default_is_stmt;
  373.     Dwarf_Sbyte             line_base;
  374.     Dwarf_Small             line_range;
  375.     Dwarf_Small             opcode_base;
  376.  
  377.         /* 
  378.             The full UCHAR_MAX number of standard opcode
  379.             lengths is used for the opcode_length table because
  380.             that is the only totally safe limit for static 
  381.             allocation to avoid malloc-ing the exact size needed.
  382.         */
  383.     Dwarf_Small             opcode_length[UCHAR_MAX];
  384.     Dwarf_Small             *include_directories;
  385.     Dwarf_File_Entry        file_entries;
  386.     
  387.         /* These are the state machine state variables. */
  388.     Dwarf_Addr              address;
  389.     Dwarf_Word              file;
  390.     Dwarf_Word              line;
  391.     Dwarf_Word              column;
  392.     Dwarf_Bool              is_stmt;
  393.     Dwarf_Bool              basic_block;
  394.     Dwarf_Bool              end_sequence;
  395.  
  396.         /* 
  397.             These pointers are used to build the list of files names        
  398.             by this cu.  cur_file_entry points to the file name being   
  399.             added, and prev_file_entry to the previous one.             
  400.         */
  401.     Dwarf_File_Entry          cur_file_entry, prev_file_entry;
  402.  
  403.     Dwarf_Sword                    i, file_entry_count, include_directories_count;
  404.  
  405.         /* 
  406.             This is the current opcode read     
  407.             from the statement program.     
  408.         */
  409.     Dwarf_Small             opcode;
  410.  
  411.         /* 
  412.         Pointer to a Dwarf_Line_Context_s structure that
  413.         contains the context such as file names and include
  414.         directories for the set of lines being generated.
  415.         */
  416.     Dwarf_Line_Context        line_context;
  417.  
  418.         /* 
  419.             This is a pointer to the current        
  420.             line being added to the line matrix.    
  421.         */
  422.     Dwarf_Line              curr_line;
  423.  
  424.         /* 
  425.             These variables are used to decode leb128 numbers.      
  426.             Leb128_num holds the decoded number, and leb128_length  
  427.             is its length in bytes.                                 
  428.         */
  429.     Dwarf_Word                leb128_num;
  430.     Dwarf_Word              leb128_length;
  431.     Dwarf_Sword            advance_line;
  432.  
  433.         /* 
  434.             This is the operand of the latest fixed_advance_pc  
  435.             extended opcode.                                        
  436.         */
  437.     Dwarf_Half              fixed_advance_pc;
  438.  
  439.         /* 
  440.             Counts the number of lines in   
  441.             the line matrix.                    
  442.         */
  443.     Dwarf_Word              line_count = 0;
  444.  
  445.         /* This is the length of an extended opcode instr.  */
  446.     Dwarf_Word          instr_length;
  447.     Dwarf_Small         ext_opcode;
  448.  
  449.         /* 
  450.             Used to chain together pointers to line table entries 
  451.         that are later used to create a block of Dwarf_Line entries.
  452.         */
  453.     Dwarf_Chain        chain_line, head_chain = NULL, curr_chain;
  454.  
  455.         /* 
  456.             This points to a block of Dwarf_Lines, a
  457.             pointer to which is returned in linebuf.
  458.         */
  459.     Dwarf_Line        *block_line;
  460.  
  461.     /* The Dwarf_Debug this die belongs to. */
  462.     Dwarf_Debug        dbg;
  463.     int resattr;
  464.     int lres;
  465.  
  466.     /* ***** BEGIN CODE ***** */
  467.  
  468.     if (error != NULL) *error = NULL;
  469.  
  470.     CHECK_DIE(die, DW_DLV_ERROR)
  471.     dbg = die->di_cu_context->cc_dbg;
  472.     if (dbg->de_debug_line == NULL) {
  473.         return(DW_DLV_NO_ENTRY);
  474.     }
  475.  
  476.     resattr = dwarf_attr(die, DW_AT_stmt_list,&stmt_list_attr,error);
  477.     if(resattr != DW_DLV_OK) {
  478.     return resattr;
  479.     }
  480.  
  481.     
  482.  
  483.     lres = dwarf_formudata(stmt_list_attr,&line_offset, error);
  484.     if(lres != DW_DLV_OK) {
  485.     return lres;
  486.     }
  487.     
  488.     if (line_offset >= dbg->de_debug_line_size) {
  489.         _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
  490.         return(DW_DLV_ERROR);
  491.     }
  492.     line_ptr = dbg->de_debug_line + line_offset;
  493.     dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR);
  494.  
  495.     /* 
  496.         If die has DW_AT_comp_dir attribute, get the
  497.         string that names the compilation directory.
  498.     */
  499.     resattr = dwarf_attr(die, DW_AT_comp_dir,&comp_dir_attr, error);
  500.     if(resattr == DW_DLV_ERROR) {
  501.         return resattr;
  502.     }
  503.     if (resattr == DW_DLV_OK) {
  504.     int cres;
  505.     char *cdir;
  506.     cres = dwarf_formstring(comp_dir_attr,&cdir, error);
  507.     if(cres == DW_DLV_ERROR){
  508.         return cres;
  509.     }else if(cres == DW_DLV_OK) {
  510.         comp_dir = cdir;
  511.     }
  512.     }
  513.     if(resattr == DW_DLV_OK) {
  514.             dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
  515.     }
  516.  
  517.         /* 
  518.             Following is a straightforward decoding of the  
  519.             statement program prologue information.         
  520.         */
  521.     READ_UNALIGNED(total_length, line_ptr, dbg->de_length_size);
  522.     line_ptr += dbg->de_length_size;
  523.     line_ptr_end = line_ptr + total_length;
  524.     if (line_ptr_end > dbg->de_debug_line + 
  525.         dbg->de_debug_line_size) {
  526.         _dwarf_error(dbg,error,DW_DLE_DEBUG_LINE_LENGTH_BAD); 
  527.         return(DW_DLV_ERROR);
  528.     }
  529.  
  530.     READ_UNALIGNED(version, line_ptr, sizeof(Dwarf_Half));
  531.     line_ptr += sizeof(Dwarf_Half);
  532.     if (version != CURRENT_VERSION_STAMP) {
  533.         _dwarf_error(dbg,error,DW_DLE_VERSION_STAMP_ERROR);
  534.         return(DW_DLV_ERROR);
  535.     }
  536.  
  537.     READ_UNALIGNED(prologue_length, line_ptr, dbg->de_length_size);
  538.     line_ptr += dbg->de_length_size;
  539.     check_line_ptr = line_ptr;
  540.  
  541.     minimum_instruction_length = *(Dwarf_Small *)line_ptr;
  542.     line_ptr = line_ptr + sizeof(Dwarf_Small);
  543.  
  544.     default_is_stmt = *(Dwarf_Small *)line_ptr;
  545.     line_ptr = line_ptr + sizeof(Dwarf_Small);
  546.  
  547.     line_base = *(Dwarf_Sbyte *)line_ptr;
  548.     line_ptr = line_ptr + sizeof(Dwarf_Sbyte);
  549.  
  550.     line_range = *(Dwarf_Small *)line_ptr;
  551.     line_ptr = line_ptr + sizeof(Dwarf_Small);
  552.  
  553.     opcode_base = *(Dwarf_Small *)line_ptr;
  554.     line_ptr = line_ptr + sizeof(Dwarf_Small);
  555.  
  556.     for (i = 1; i < opcode_base; i++) {
  557.         opcode_length[i] = *(Dwarf_Small *)line_ptr;
  558.         line_ptr = line_ptr + sizeof(Dwarf_Small);
  559.     }
  560.  
  561.     include_directories_count = 0;
  562.     include_directories = line_ptr;
  563.     while ((*(char *)line_ptr) != '\0') {
  564.         line_ptr = line_ptr + strlen((char *)line_ptr) + 1;
  565.         include_directories_count++;
  566.     }
  567.     line_ptr++;
  568.  
  569.     file_entry_count = 0;
  570.     file_entries = prev_file_entry = NULL;
  571.     while (*(char *)line_ptr != '\0') {
  572.  
  573.         cur_file_entry = (Dwarf_File_Entry)
  574.             _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1);
  575.         if (cur_file_entry == NULL){ 
  576.             _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
  577.         return(DW_DLV_ERROR);
  578.     }
  579.  
  580.         cur_file_entry->fi_file_name = (Dwarf_Small *)line_ptr;
  581.         line_ptr = line_ptr + strlen((char *)line_ptr) + 1;
  582.  
  583.         cur_file_entry->fi_dir_index = 
  584.             _dwarf_decode_u_leb128(line_ptr,&leb128_length);
  585.         line_ptr = line_ptr + leb128_length;
  586.  
  587.         cur_file_entry->fi_time_last_mod = 
  588.             _dwarf_decode_u_leb128(line_ptr,&leb128_length);
  589.         line_ptr = line_ptr + leb128_length;
  590.  
  591.         cur_file_entry->fi_file_length = 
  592.             _dwarf_decode_u_leb128(line_ptr,&leb128_length);
  593.         line_ptr = line_ptr + leb128_length;
  594.  
  595.         if (file_entries == NULL) 
  596.             file_entries = cur_file_entry;
  597.         else 
  598.             prev_file_entry->fi_next = cur_file_entry;
  599.         prev_file_entry = cur_file_entry;
  600.  
  601.         file_entry_count++;
  602.     }
  603.     line_ptr++;
  604.  
  605.     if (line_ptr != check_line_ptr + prologue_length) {
  606.         _dwarf_error(dbg,error,DW_DLE_LINE_PROLOG_LENGTH_BAD);
  607.         return(DW_DLV_ERROR);
  608.     }
  609.  
  610.         /* Set up context structure for this set of lines. */
  611.     line_context = (Dwarf_Line_Context)
  612.     _dwarf_get_alloc(dbg, DW_DLA_LINE_CONTEXT, 1);
  613.     if (line_context == NULL) {
  614.     _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
  615.     return(DW_DLV_ERROR);
  616.     }
  617.  
  618.         /* Initialize the state machine.    */
  619.     address = 0;
  620.     file = 1;
  621.     line = 1;
  622.     column = 0;
  623.     is_stmt = default_is_stmt;
  624.     basic_block = false;
  625.     end_sequence = false;
  626.  
  627.         /* Start of statement program.  */
  628.     while (line_ptr < line_ptr_end) {
  629.         
  630.         opcode = *(Dwarf_Small *)line_ptr;
  631.         line_ptr++;
  632.         switch (opcode) {
  633.             
  634.                 /* 
  635.                     These are special opcodes between opcode_base
  636.                     and UCHAR_MAX.                            
  637.                 */
  638.             default : {
  639.  
  640.                 opcode = opcode - opcode_base;
  641.                 address = address + minimum_instruction_length * 
  642.             (opcode / line_range);
  643.                 line = line + line_base + opcode % line_range;
  644.  
  645.         if(dolines) {
  646.                   curr_line = (Dwarf_Line)_dwarf_get_alloc(dbg, DW_DLA_LINE, 1);
  647.                   if (curr_line == NULL) {
  648.                     _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
  649.                     return(DW_DLV_ERROR);
  650.                   }
  651.  
  652.                   curr_line->li_address = address;
  653.                   curr_line->li_addr_line.li_l_data.li_file = file;
  654.                   curr_line->li_addr_line.li_l_data.li_line = line;
  655.                   curr_line->li_addr_line.li_l_data.li_column = column;
  656.                   curr_line->li_addr_line.li_l_data.li_is_stmt = is_stmt;
  657.                   curr_line->li_addr_line.li_l_data.li_basic_block = basic_block;
  658.                   curr_line->li_addr_line.li_l_data.li_end_sequence = end_sequence;
  659.           curr_line->li_context = line_context;
  660.                   line_count++;
  661.  
  662.                   chain_line = (Dwarf_Chain)
  663.                     _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
  664.                   if (chain_line == NULL) {
  665.                     _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
  666.                     return(DW_DLV_ERROR);
  667.                   }
  668.                   chain_line->ch_item = curr_line;
  669.   
  670.                   if (head_chain == NULL) 
  671.                     head_chain = curr_chain = chain_line;
  672.                   else {
  673.                     curr_chain->ch_next = chain_line;
  674.                     curr_chain = chain_line;
  675.                   }
  676.                 }
  677.  
  678.                 basic_block = false;
  679.                 break;
  680.             }
  681.  
  682.             case DW_LNS_copy : {
  683.                 if (opcode_length[DW_LNS_copy] != 0) {
  684.                     _dwarf_error(dbg,error,DW_DLE_LINE_NUM_OPERANDS_BAD);
  685.                     return(DW_DLV_ERROR);
  686.                 }
  687.  
  688.         if(dolines) {
  689.  
  690.                   curr_line = (Dwarf_Line)_dwarf_get_alloc(dbg, DW_DLA_LINE, 1);
  691.                   if (curr_line == NULL) {
  692.                     _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
  693.                     return(DW_DLV_ERROR);
  694.                   }
  695.  
  696.                   curr_line->li_address = address;
  697.                   curr_line->li_addr_line.li_l_data.li_file = file;
  698.                   curr_line->li_addr_line.li_l_data.li_line = line;
  699.                   curr_line->li_addr_line.li_l_data.li_column = column;
  700.                   curr_line->li_addr_line.li_l_data.li_is_stmt = is_stmt;
  701.                   curr_line->li_addr_line.li_l_data.li_basic_block = basic_block;
  702.                   curr_line->li_addr_line.li_l_data.li_end_sequence = end_sequence;
  703.           curr_line->li_context = line_context;
  704.                   line_count++;
  705.  
  706.                   chain_line = (Dwarf_Chain) 
  707.             _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
  708.                   if (chain_line == NULL) {
  709.                     _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
  710.                     return(DW_DLV_ERROR);
  711.                   }
  712.                   chain_line->ch_item = curr_line;
  713.                   if (head_chain == NULL) 
  714.             head_chain = curr_chain = chain_line;
  715.                   else {
  716.                     curr_chain->ch_next = chain_line;
  717.                     curr_chain = chain_line;
  718.                   }
  719.           }
  720.  
  721.                 basic_block = false;
  722.                 break;
  723.             }
  724.  
  725.             case DW_LNS_advance_pc : {
  726.                 if (opcode_length[DW_LNS_advance_pc] != 1) {
  727.                     _dwarf_error(dbg,error,DW_DLE_LINE_NUM_OPERANDS_BAD);
  728.                     return(DW_DLV_ERROR);
  729.                 }
  730.  
  731.         DECODE_LEB128_UWORD(line_ptr, leb128_num)
  732.                 address = address + minimum_instruction_length * leb128_num;
  733.                 break;
  734.             }
  735.  
  736.             case DW_LNS_advance_line : {
  737.                 if (opcode_length[DW_LNS_advance_line] != 1) {
  738.                     _dwarf_error(dbg,error,DW_DLE_LINE_NUM_OPERANDS_BAD);
  739.                     return(DW_DLV_ERROR);
  740.                 }
  741.  
  742.         DECODE_LEB128_SWORD(line_ptr, advance_line)
  743.                 line = line + advance_line;
  744.                 break;
  745.             }
  746.  
  747.             case DW_LNS_set_file : {
  748.                 if (opcode_length[DW_LNS_set_file] != 1) {
  749.                     _dwarf_error(dbg,error,DW_DLE_LINE_NUM_OPERANDS_BAD);
  750.                     return(DW_DLV_ERROR);
  751.                 }
  752.  
  753.         DECODE_LEB128_UWORD(line_ptr, file)
  754.                 break;
  755.             }
  756.  
  757.             case DW_LNS_set_column : {
  758.                 if (opcode_length[DW_LNS_set_column] != 1) {
  759.                     _dwarf_error(dbg,error,DW_DLE_LINE_NUM_OPERANDS_BAD);
  760.                     return(DW_DLV_ERROR);
  761.                 }
  762.  
  763.         DECODE_LEB128_UWORD(line_ptr, column)
  764.                 break;
  765.             }
  766.  
  767.             case DW_LNS_negate_stmt : {
  768.                 if (opcode_length[DW_LNS_negate_stmt] != 0) {
  769.                     _dwarf_error(dbg,error,DW_DLE_LINE_NUM_OPERANDS_BAD);
  770.                     return(DW_DLV_ERROR);
  771.                 }
  772.  
  773.                 is_stmt = !is_stmt;
  774.                 break;
  775.             }
  776.  
  777.             case DW_LNS_set_basic_block : {
  778.                 if (opcode_length[DW_LNS_set_basic_block] != 0) {
  779.                     _dwarf_error(dbg,error,DW_DLE_LINE_NUM_OPERANDS_BAD);
  780.                     return(DW_DLV_ERROR);
  781.                 }
  782.  
  783.                 basic_block = true;
  784.                 break;
  785.             }
  786.  
  787.             case DW_LNS_const_add_pc : {
  788.                 opcode = UCHAR_MAX - opcode_base;
  789.                 address = address + minimum_instruction_length *
  790.             (opcode / line_range);
  791.  
  792.                 break;
  793.             }
  794.  
  795.             case DW_LNS_fixed_advance_pc : {
  796.                 if (opcode_length[DW_LNS_fixed_advance_pc] != 1) {
  797.                     _dwarf_error(dbg,error,DW_DLE_LINE_NUM_OPERANDS_BAD);
  798.                     return(DW_DLV_ERROR);
  799.                 }
  800.  
  801.         READ_UNALIGNED(fixed_advance_pc, line_ptr, sizeof(Dwarf_Half));
  802.                 line_ptr += sizeof(Dwarf_Half);
  803.                 address = address + fixed_advance_pc;
  804.                 break;
  805.             }
  806.  
  807.             case DW_EXTENDED_OPCODE : {
  808.         DECODE_LEB128_UWORD(line_ptr, instr_length)
  809.                 ext_opcode = *(Dwarf_Small *)line_ptr;
  810.                 line_ptr++;
  811.                 switch (ext_opcode) {
  812.                     
  813.                     case DW_LNE_end_sequence : {
  814.                         end_sequence = true;
  815.  
  816.                 if(dolines) {
  817.                           curr_line = (Dwarf_Line)
  818.                 _dwarf_get_alloc(dbg, DW_DLA_LINE, 1);
  819.                           if (curr_line == NULL) {
  820.                             _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
  821.                             return(DW_DLV_ERROR);
  822.                           }
  823.  
  824.                           curr_line->li_address = address;
  825.                           curr_line->li_addr_line.li_l_data.li_file = file;
  826.                           curr_line->li_addr_line.li_l_data.li_line = line;
  827.                           curr_line->li_addr_line.li_l_data.li_column = column;
  828.                           curr_line->li_addr_line.li_l_data.li_is_stmt = false;
  829.                           curr_line->li_addr_line.li_l_data.li_basic_block = basic_block;
  830.                           curr_line->li_addr_line.li_l_data.li_end_sequence = end_sequence;
  831.               curr_line->li_context = line_context;
  832.                           line_count++;
  833.  
  834.                           chain_line = (Dwarf_Chain)
  835.                 _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
  836.                           if (chain_line == NULL) {
  837.                             _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
  838.                             return(DW_DLV_ERROR);
  839.                           }
  840.                           chain_line->ch_item = curr_line;
  841.  
  842.                           if (head_chain == NULL) 
  843.                             head_chain = curr_chain = chain_line;
  844.                           else {
  845.                             curr_chain->ch_next = chain_line;
  846.                             curr_chain = chain_line;
  847.                           }
  848.             }
  849.  
  850.                         address = 0;
  851.                         file = 1;
  852.                         line = 1;
  853.                         column = 0;
  854.                         is_stmt = default_is_stmt;
  855.                         basic_block = false;
  856.                         end_sequence = false;
  857.  
  858.                         break;
  859.                     }
  860.  
  861.                     case DW_LNE_set_address : {
  862.                         if (instr_length - 1 == dbg->de_length_size) {
  863.                 READ_UNALIGNED(address, line_ptr,
  864.                 dbg->de_length_size);
  865.                             if(doaddrs) {
  866.                               curr_line = (Dwarf_Line)_dwarf_get_alloc(dbg, DW_DLA_LINE, 1);                  if (curr_line == NULL) {
  867.                                 _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
  868.                                 return(DW_DLV_ERROR);
  869.                               }
  870.  
  871.                               curr_line->li_address = address;
  872.                   curr_line->li_addr_line.li_offset = 
  873.                        line_ptr - dbg->de_debug_line;
  874.  
  875.                               line_count++;
  876.  
  877.                               chain_line = (Dwarf_Chain)
  878.                                 _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
  879.                               if (chain_line == NULL) {
  880.                                 _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
  881.                                 return(DW_DLV_ERROR);
  882.                               }
  883.                               chain_line->ch_item = curr_line;
  884.              
  885.                               if (head_chain == NULL)
  886.                                 head_chain = curr_chain = chain_line;
  887.                               else {
  888.                                 curr_chain->ch_next = chain_line;
  889.                                 curr_chain = chain_line;
  890.                               }
  891.                             }
  892.  
  893.                             line_ptr += dbg->de_length_size;
  894.                         }
  895.                         else {
  896.                             _dwarf_error(dbg,error,
  897.                                 DW_DLE_LINE_SET_ADDR_ERROR);
  898.                             return(DW_DLV_ERROR);
  899.                         }
  900.  
  901.                         break;
  902.                     }
  903.  
  904.                     case DW_LNE_define_file : {
  905.  
  906.               if(dolines) {
  907.                         cur_file_entry = (Dwarf_File_Entry)
  908.                             _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1);
  909.                         if (cur_file_entry == NULL) {
  910.                             _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
  911.                             return(DW_DLV_ERROR);
  912.                         }
  913.  
  914.                         cur_file_entry->fi_file_name = (Dwarf_Small *)line_ptr;
  915.                         line_ptr = line_ptr + strlen((char *)line_ptr) + 1;
  916.  
  917.                         cur_file_entry->fi_dir_index = 
  918.                             _dwarf_decode_u_leb128(line_ptr,&leb128_length);
  919.                         line_ptr = line_ptr + leb128_length;
  920.  
  921.                         cur_file_entry->fi_time_last_mod = 
  922.                             _dwarf_decode_u_leb128(line_ptr,&leb128_length);
  923.                         line_ptr = line_ptr + leb128_length;
  924.  
  925.                         cur_file_entry->fi_file_length = 
  926.                             _dwarf_decode_u_leb128(line_ptr,&leb128_length);
  927.                         line_ptr = line_ptr + leb128_length;
  928.  
  929.                         if (file_entries == NULL) 
  930.                             file_entries = cur_file_entry;
  931.                         else 
  932.                             prev_file_entry->fi_next = cur_file_entry;
  933.                         prev_file_entry = cur_file_entry;
  934.  
  935.                         file_entry_count++;
  936.                       }
  937.                         break;
  938.                     }
  939.                                 
  940.                     default : {
  941.                         _dwarf_error(dbg,error,DW_DLE_LINE_EXT_OPCODE_BAD);
  942.                         return(DW_DLV_ERROR);
  943.                     }
  944.                 }
  945.  
  946.             }
  947.         }
  948.     }
  949.  
  950.     block_line = (Dwarf_Line *)
  951.         _dwarf_get_alloc(dbg, DW_DLA_LIST, line_count);
  952.     if (block_line == NULL) {
  953.         _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
  954.         return(DW_DLV_ERROR);
  955.     }
  956.  
  957.     curr_chain = head_chain;
  958.     for (i = 0; i < line_count; i++) {
  959.         *(block_line + i) = curr_chain->ch_item;
  960.         head_chain = curr_chain;
  961.         curr_chain = curr_chain->ch_next;
  962.         dwarf_dealloc(dbg, head_chain, DW_DLA_CHAIN);
  963.     }
  964.  
  965.     line_context->lc_file_entries = file_entries;
  966.     line_context->lc_file_entry_count = file_entry_count;
  967.     line_context->lc_include_directories = include_directories;
  968.     line_context->lc_include_directories_count = include_directories_count;
  969.     line_context->lc_line_count = line_count;
  970.     line_context->lc_compilation_directory = comp_dir;
  971.     line_context->lc_dbg = dbg;
  972.     *count = line_count;
  973.  
  974.     *linebuf = block_line;
  975.     return(DW_DLV_OK);
  976. }
  977. int
  978. dwarf_srclines (
  979.     Dwarf_Die       die,
  980.     Dwarf_Line      **linebuf,
  981.     Dwarf_Signed    *linecount,
  982.     Dwarf_Error     *error
  983. )
  984. {
  985.     Dwarf_Signed count;
  986.     int res;
  987.     res = _dwarf_internal_srclines(die,linebuf,
  988.          &count,/*addrlist=*/false,
  989.         /*linelist=*/ true,error);
  990.     if(res != DW_DLV_OK) {
  991.         return res;
  992.     }
  993.         *linecount = count;
  994.     return res;
  995. }
  996.  
  997.  
  998.  
  999.  
  1000.  
  1001. int
  1002. dwarf_linebeginstatement (
  1003.     Dwarf_Line      line,
  1004.     Dwarf_Bool     *return_bool,
  1005.     Dwarf_Error     *error
  1006. )
  1007. {
  1008.     if (line == NULL || return_bool == 0) {
  1009.         _dwarf_error(NULL,error,DW_DLE_DWARF_LINE_NULL);
  1010.         return(DW_DLV_ERROR);
  1011.     }
  1012.  
  1013.     *return_bool = (line->li_addr_line.li_l_data.li_is_stmt);
  1014.     return DW_DLV_OK;
  1015. }
  1016.  
  1017. int
  1018. dwarf_lineendsequence (
  1019.     Dwarf_Line          line,
  1020.     Dwarf_Bool *        return_bool,
  1021.     Dwarf_Error         *error
  1022. )
  1023. {
  1024.     if (line == NULL) {
  1025.         _dwarf_error(NULL,error,DW_DLE_DWARF_LINE_NULL);
  1026.         return(DW_DLV_ERROR);
  1027.     }
  1028.  
  1029.     *return_bool = (line->li_addr_line.li_l_data.li_end_sequence);
  1030.     return DW_DLV_OK;
  1031. }
  1032.  
  1033.  
  1034. int
  1035. dwarf_lineno (
  1036.     Dwarf_Line      line,
  1037.     Dwarf_Unsigned  *ret_lineno,
  1038.     Dwarf_Error     *error
  1039. )
  1040. {
  1041.     if (line == NULL || ret_lineno == 0) {
  1042.         _dwarf_error(NULL,error,DW_DLE_DWARF_LINE_NULL);
  1043.         return(DW_DLV_ERROR);
  1044.     }
  1045.  
  1046.     *ret_lineno = (line->li_addr_line.li_l_data.li_line);  
  1047.     return DW_DLV_OK;
  1048. }
  1049.  
  1050.  
  1051. int
  1052. dwarf_lineaddr (
  1053.     Dwarf_Line      line,
  1054.     Dwarf_Addr    * ret_lineaddr,
  1055.     Dwarf_Error     *error
  1056. )
  1057. {
  1058.     if (line == NULL || ret_lineaddr == 0) {
  1059.         _dwarf_error(NULL,error,DW_DLE_DWARF_LINE_NULL);
  1060.         return(DW_DLV_ERROR);
  1061.     }
  1062.  
  1063.     *ret_lineaddr = (line->li_address);   
  1064.     return DW_DLV_OK;
  1065. }
  1066.  
  1067.  
  1068. int
  1069. dwarf_lineoff (
  1070.     Dwarf_Line      line,
  1071.     Dwarf_Signed  * ret_lineoff,
  1072.     Dwarf_Error     *error
  1073. )
  1074. {
  1075.     if (line == NULL || ret_lineoff == 0) {
  1076.         _dwarf_error(NULL,error,DW_DLE_DWARF_LINE_NULL);
  1077.         return(DW_DLV_ERROR);
  1078.     }
  1079.  
  1080.     *ret_lineoff = (line->li_addr_line.li_l_data.li_column==0 ? -1 : line->li_addr_line.li_l_data.li_column);  
  1081.     return DW_DLV_OK;
  1082. }
  1083.  
  1084.  
  1085. int
  1086. dwarf_linesrc (
  1087.     Dwarf_Line      line,
  1088.     char **         ret_linesrc,
  1089.     Dwarf_Error     *error
  1090. )
  1091. {
  1092.     Dwarf_Signed            i;
  1093.     Dwarf_File_Entry        file_entry;
  1094.     Dwarf_Small             *name_buffer;
  1095.     Dwarf_Small             *include_directories;
  1096.     Dwarf_Debug            dbg;
  1097.  
  1098.     if (line == NULL) {
  1099.         _dwarf_error(NULL,error,DW_DLE_DWARF_LINE_NULL);
  1100.         return(DW_DLV_ERROR);
  1101.     }
  1102.  
  1103.     if (line->li_context == NULL) {
  1104.         _dwarf_error(NULL,error,DW_DLE_LINE_CONTEXT_NULL);
  1105.         return(DW_DLV_ERROR);
  1106.     }
  1107.     dbg = line->li_context->lc_dbg;
  1108.  
  1109.     if (line->li_addr_line.li_l_data.li_file > line->li_context->lc_file_entry_count) {
  1110.         _dwarf_error(dbg, error, DW_DLE_LINE_FILE_NUM_BAD);
  1111.         return(DW_DLV_ERROR);
  1112.     }
  1113.  
  1114.     file_entry = line->li_context->lc_file_entries;
  1115.     for (i = line->li_addr_line.li_l_data.li_file - 1; i > 0; i--)
  1116.         file_entry = file_entry->fi_next;
  1117.  
  1118.     if (file_entry->fi_file_name == NULL) {
  1119.         _dwarf_error(dbg, error, DW_DLE_NO_FILE_NAME);
  1120.        return(DW_DLV_ERROR);
  1121.     }
  1122.  
  1123.     if (*(char *)file_entry->fi_file_name == '/')  {
  1124.         *ret_linesrc = ((char *)file_entry->fi_file_name);
  1125.     return DW_DLV_OK;
  1126.     }
  1127.  
  1128.     if (file_entry->fi_dir_index == 0) {
  1129.  
  1130.     if (line->li_context->lc_compilation_directory == NULL) {
  1131.         _dwarf_error(dbg, error, DW_DLE_NO_COMP_DIR);
  1132.         return(DW_DLV_ERROR);
  1133.     }
  1134.  
  1135.         name_buffer = _dwarf_get_alloc(line->li_context->lc_dbg, DW_DLA_STRING,
  1136.             strlen(line->li_context->lc_compilation_directory) + 1 +
  1137.         strlen((char *)file_entry->fi_file_name) + 1);
  1138.         if (name_buffer == NULL) {
  1139.             _dwarf_error(line->li_context->lc_dbg,error,DW_DLE_ALLOC_FAIL);
  1140.             return(DW_DLV_ERROR);
  1141.         }
  1142.  
  1143.         strcpy((char *)name_buffer,line->li_context->lc_compilation_directory);
  1144.     strcat((char *)name_buffer,"/");
  1145.         strcat((char *)name_buffer,(char *)file_entry->fi_file_name);
  1146.         *ret_linesrc = ((char *)name_buffer);
  1147.     return DW_DLV_OK;
  1148.     }
  1149.  
  1150.     if (file_entry->fi_dir_index > 
  1151.         line->li_context->lc_include_directories_count) {
  1152.         _dwarf_error(dbg, error, DW_DLE_INCL_DIR_NUM_BAD);
  1153.         return(DW_DLV_ERROR);
  1154.     }
  1155.  
  1156.     include_directories = line->li_context->lc_include_directories;
  1157.     for (i = file_entry->fi_dir_index - 1; i > 0; i--) 
  1158.         include_directories += strlen((char *)include_directories) + 1;
  1159.  
  1160.     name_buffer = _dwarf_get_alloc(dbg, DW_DLA_STRING,
  1161.     (*include_directories == '/' ? 
  1162.         0 : strlen(line->li_context->lc_compilation_directory) + 1) +
  1163.     strlen((char *)include_directories) + 1 +
  1164.         strlen((char *)file_entry->fi_file_name) + 1);
  1165.     if (name_buffer == NULL) {
  1166.         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
  1167.         return(DW_DLV_ERROR);
  1168.     }
  1169.  
  1170.     if (*include_directories != '/')
  1171.     strcpy(name_buffer, line->li_context->lc_compilation_directory);
  1172.     else
  1173.     strcpy(name_buffer, "");
  1174.     strcat((char *)name_buffer,(char *)include_directories);
  1175.     strcat((char *)name_buffer,"/");
  1176.     strcat((char *)name_buffer,(char *)file_entry->fi_file_name);
  1177.     *ret_linesrc = ((char *)name_buffer);
  1178.     return DW_DLV_OK;
  1179. }
  1180.  
  1181.  
  1182. int
  1183. dwarf_lineblock (
  1184.     Dwarf_Line      line,
  1185.     Dwarf_Bool     *return_bool,
  1186.     Dwarf_Error     *error
  1187. )
  1188. {
  1189.     if (line == NULL) {
  1190.         _dwarf_error(NULL,error,DW_DLE_DWARF_LINE_NULL);
  1191.         return(DW_DLV_ERROR);
  1192.     }
  1193.  
  1194.     *return_bool = (line->li_addr_line.li_l_data.li_basic_block);   
  1195.     return DW_DLV_OK;
  1196. }
  1197.  
  1198.  
  1199. #if 0 /* Ignore this.  This needs major re-work. */
  1200. /* 
  1201.     This routine works by looking for exact matches between 
  1202.     the current line address and pc, and crossovers from
  1203.     from less than pc value to greater than.  At each line
  1204.     that satisfies the above, it records a pointer to the
  1205.     line, and the difference between the address and pc.
  1206.     It then scans these pointers and picks out those with
  1207.     the smallest difference between pc and address.         
  1208. */
  1209. int
  1210. dwarf_pclines (
  1211.     Dwarf_Debug     dbg,
  1212.     Dwarf_Addr      pc,
  1213.     Dwarf_Line      **linebuf,
  1214.     Dwarf_Signed    slide,
  1215.     Dwarf_Signed    *linecount,
  1216.     Dwarf_Error     *error
  1217. )
  1218. {
  1219.     /* 
  1220.         Scans the line matrix for the current cu    
  1221.         to which a pointer exists in dbg.           
  1222.     */
  1223.     Dwarf_Line      line;
  1224.     Dwarf_Line      prev_line;
  1225.  
  1226.     /* 
  1227.         These flags are for efficiency reasons.                             
  1228.         Check_line is true initially, but set false when the address    
  1229.         of the current line is greater than pc.  It is set true only
  1230.         when the address of the current line falls below pc.  This      
  1231.         assumes that addresses within the same segment increase, and
  1232.         we are only interested in the switch from a less than pc            
  1233.         address to a greater than.                                      
  1234.         First_line is set true initially, but set false after the first 
  1235.         line is scanned.  This is to prevent looking at the address of
  1236.         previous line when slide is DW_DLS_BACKWARD, and the first line
  1237.         is being scanned.                                               
  1238.     */
  1239.     Dwarf_Bool          check_line, first_line;
  1240.  
  1241.     /* 
  1242.         Diff tracks the smallest difference a line address  
  1243.         and the input pc value.                             
  1244.     */
  1245.     Dwarf_Signed        diff, i;
  1246.  
  1247.     /* 
  1248.         For the slide = DW_DLS_BACKWARD case, pc_less is the value  
  1249.         of the address of the line immediately preceding the first
  1250.         line that has value greater than pc.                    
  1251.         For the slide = DW_DLS_FORWARD case, pc_more is the values  
  1252.         of address for the first line that is greater than pc.  
  1253.         Diff is the difference between either of the these values
  1254.         and pc.                                                     
  1255.     */
  1256.     Dwarf_Addr      pc_less, pc_more;
  1257.  
  1258.     /* 
  1259.         Pc_line_buf points to a chain of pointers to lines of which 
  1260.         those with a diff equal to the smallest difference will be
  1261.         returned.                                                   
  1262.     */
  1263.     Dwarf_Line      *pc_line_buf, *pc_line;
  1264.  
  1265.     /* 
  1266.         Chain_count counts the number of lines in the above chain   
  1267.         for which the diff is equal to the smallest difference  
  1268.         This is the number returned by this routine.                    
  1269.     */
  1270.     Dwarf_Signed        chain_count;
  1271.  
  1272.     chain_head = NULL;
  1273.  
  1274.     check_line = true;
  1275.     first_line = true;
  1276.     diff = MAX_LINE_DIFF;
  1277.  
  1278.     for (i = 0; i < dbg->de_cu_line_count; i++) {
  1279.  
  1280.         line = *(dbg->de_cu_line_ptr + i);
  1281.         prev_line = first_line ? NULL : *(dbg->de_cu_line_ptr + i - 1);
  1282.  
  1283.         if (line->li_address == pc) {
  1284.             chain_ptr = (struct chain *)
  1285.                 _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
  1286.             if (chain_ptr == NULL) {
  1287.                 _dwarf_error(NULL,error,DW_DLE_ALLOC_FAIL);
  1288.                 return(DW_DLV_ERROR);
  1289.             }
  1290.  
  1291.             chain_ptr->line = line;
  1292.             chain_ptr->diff = diff = 0;
  1293.             chain_ptr->next = chain_head;
  1294.             chain_head = chain_ptr;
  1295.         }
  1296.         else 
  1297.             /* 
  1298.                 Look for crossover from less than pc address    
  1299.                 to greater than.                                
  1300.             */
  1301.             if (check_line && line->li_address > pc &&
  1302.                 (first_line ? 0 : prev_line->li_address) < pc)
  1303.  
  1304.                 if (slide == DW_DLS_BACKWARD && !first_line) { 
  1305.                     pc_less = prev_line->li_address;
  1306.                     if (pc - pc_less <= diff) {
  1307.                         chain_ptr = (struct chain *)
  1308.                             _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
  1309.                         if (chain_ptr == NULL) {
  1310.                             _dwarf_error(NULL,error,DW_DLE_ALLOC_FAIL);
  1311.                             return(DW_DLV_ERROR);
  1312.                         }
  1313.  
  1314.                         chain_ptr->line = prev_line;
  1315.                         chain_ptr->diff = diff = pc - pc_less;
  1316.                         chain_ptr->next = chain_head;
  1317.                         chain_head = chain_ptr;
  1318.                     }
  1319.                     check_line = false;
  1320.                 }
  1321.                 else if (slide == DW_DLS_FORWARD) { 
  1322.                     pc_more = line->li_address;
  1323.                     if (pc_more - pc <= diff) {
  1324.                         chain_ptr = (struct chain *)
  1325.                             _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
  1326.                         if (chain_ptr == NULL) {
  1327.                             _dwarf_error(NULL,error,DW_DLE_ALLOC_FAIL);
  1328.                             return(DW_DLV_ERROR);
  1329.                         }
  1330.  
  1331.                         chain_ptr->line = line;
  1332.                         chain_ptr->diff = diff = pc_more - pc;
  1333.                         chain_ptr->next = chain_head;
  1334.                         chain_head = chain_ptr;
  1335.                     }
  1336.                     check_line = false;
  1337.                 }
  1338.             else
  1339.                 /* Check addresses only when they go    */
  1340.                 /* below pc.                            */
  1341.                 if (line->li_address < pc)
  1342.                     check_line = true;
  1343.         
  1344.         first_line = false;
  1345.     }
  1346.  
  1347.     chain_count = 0;
  1348.     for (chain_ptr = chain_head; chain_ptr != NULL; 
  1349.         chain_ptr = chain_ptr->next)
  1350.         if (chain_ptr->diff == diff) chain_count++;
  1351.  
  1352.     pc_line_buf = pc_line = (Dwarf_Line)
  1353.         _dwarf_get_alloc(dbg, DW_DLA_LIST, chain_count);
  1354.     for (chain_ptr = chain_head; chain_ptr != NULL; 
  1355.         chain_ptr = chain_ptr->next)
  1356.         if (chain_ptr->diff == diff) {
  1357.             *pc_line = chain_ptr->line;
  1358.             pc_line++;
  1359.         }
  1360.  
  1361.     for (chain_ptr = chain_head; chain_ptr != NULL; ) {
  1362.         chain_head = chain_ptr;
  1363.         chain_ptr = chain_ptr->next;
  1364.         dwarf_dealloc(dbg, chain_head, DW_DLA_CHAIN);
  1365.     }
  1366.  
  1367.     *linebuf = pc_line_buf;
  1368.     return(chain_count);
  1369. }
  1370. #endif
  1371.  
  1372.  
  1373. /*
  1374.     Return DW_DLV_OK or, if error,
  1375.     DW_DLV_ERROR.
  1376.  
  1377.     Thru pointers, return 2 arrays and a count
  1378.     for rqs.
  1379. */
  1380. int
  1381. _dwarf_line_address_offsets(Dwarf_Debug dbg,
  1382.         Dwarf_Die die,
  1383.         Dwarf_Addr **addrs,
  1384.         Dwarf_Off  **offs,
  1385.         Dwarf_Unsigned *returncount,
  1386.         Dwarf_Error *err)
  1387. {
  1388.   Dwarf_Addr *laddrs;
  1389.   Dwarf_Off  *loffsets;
  1390.   Dwarf_Signed lcount;
  1391.   Dwarf_Signed i;
  1392.   int res;
  1393.   Dwarf_Line      *linebuf;
  1394.   res = _dwarf_internal_srclines(die,&linebuf,
  1395.          &lcount,/*addrlist=*/true,
  1396.         /*linelist=*/ false,err);
  1397.   if(res != DW_DLV_OK) {
  1398.         return res;
  1399.   }
  1400.   laddrs = (Dwarf_Addr *)
  1401.         _dwarf_get_alloc(dbg, DW_DLA_ADDR, lcount);
  1402.   if (laddrs == NULL) {
  1403.         _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
  1404.         return(DW_DLV_ERROR);
  1405.   }
  1406.   loffsets = (Dwarf_Off *)
  1407.         _dwarf_get_alloc(dbg, DW_DLA_ADDR, lcount);
  1408.   if (loffsets == NULL) {
  1409.         _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
  1410.         return(DW_DLV_ERROR);
  1411.   }
  1412.  
  1413.   for (i = 0; i < lcount; i++) {
  1414.         laddrs[i] = linebuf[i]->li_address;
  1415.         loffsets[i] = linebuf[i] ->li_addr_line.li_offset;
  1416.     dwarf_dealloc(dbg,linebuf[i],DW_DLA_LINE);
  1417.   }
  1418.   dwarf_dealloc(dbg,linebuf,DW_DLA_LIST);
  1419.   *returncount = lcount;
  1420.   *offs = loffsets;
  1421.   *addrs = laddrs;
  1422.   return DW_DLV_OK;
  1423. }
  1424.